﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
using System.IO;
using AgileRollover.Utility;
using Polenter.Serialization;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Server;

//Adding a comment to check the build works - trying again
namespace AgileRollover
{
    class Program
    {
        /* Basic Pattern:
         * Connect to specified Team Project
         * Get the current data/time
         * Get all Teams in the project
         * For each team:
         *      Get area paths
         *      Get iterations
         *          Find the most recent sprint
         *          Find the current/next sprint
         *      If now > most recent & current/next >= now
         *          For each area path
         *              Update iteration on not-done tasks and their parents
         * First Cloud Build
         */
        //
        #region Constants
        public const String areas = "ProjectModelHierarchy";
        public const String iterations = "ProjectLifecycle";
        #endregion Constants
        public static Options options;
        public static SharpSerializer oSer;
        public static ArgumentParser aOptions;
        public static String filepath;
        public static TfsJSON tfsReader;
        public static List<Project> projectList;

        static void Main(string[] args)
        {
            options = new Options();
            aOptions = new ArgumentParser(args);
            optionSetter();

            if (options.CollectionUri == null)
            {
                Console.WriteLine("Please specify a team project collection using the /collection:<url> option\n\n");
                Console.WriteLine("-For silent operation, specify teams with /teams:<team1>,<team2>\n");
                Console.WriteLine("-Optionally specify /username:<username> and /password:<password> \n to use an account that can connect to the Data Tier and is a TPC Admin\n");
                Console.WriteLine("-Export settings for a successful rollover with the \n /o:<filename> option.\n");
                Console.WriteLine("-Import settings for a silent run with the \n /f:<filename> option.");
                Console.WriteLine("-Export selected teams without rollover using /exportTeams /f:<filename> option.");
                
            } 
            else
            {
                if (!options.hasTfsTeams())
                {
                    tfsReader = new TfsJSON(options.CollectionUri);
                    projectList = tfsReader.TfsProjectHierarchy();
                    optionMenu();
                }

                if (aOptions.getArg("importTeams") != null)
                {
                    //read all the teams into options.TfsTeams
                    //rollTeam.ImportTeam(team.Key, team.Value);
                }

                if (options.hasTfsTeams())
                {
                    if (aOptions.getArg("exportTeams") != null)
                    {
                        if (filepath != null)
                            optionWriter(filepath);
                    }
                    else
                    {
                        foreach (TfsTeam team in options.TfsTeams)
                        {
                            Console.WriteLine(team.Name+": Querying for work to roll forward");
                            team.rollWorkForward();
                        }
                        if (filepath != null)
                            optionWriter(filepath);
                    }
                }
            }
        }

        static void optionSetter()
        {
            try
            {
                if (aOptions.hasParameters())
                {
                    if (aOptions.getArg("f") != null)
                    {
                        optionReader(aOptions.getArg("f"));
                        foreach (TfsTeam team in options.TfsTeams)
                        {
                            //must reinitialize team iterations every time
                            tfsReader = new TfsJSON(options.CollectionUri);
                            team.InitIterationsFromTFS(tfsReader);
                        }
                    }
                    else
                    {
                        filepath = aOptions.getArg("o");
                        options.FinishedState = aOptions.getArg("finishedState");
                        options.CollectionUri = aOptions.getArg("collection");
                        options.Username = aOptions.getArg("username");
                        options.Password = aOptions.getArg("password");
                        using (var tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(options.CollectionUri)))
                            {
                                IRegistration regService = (IRegistration)tpc.GetService(typeof(IRegistration));
                                string[] splitout = regService.GetRegistrationEntries("WorkItemTracking")[0].Databases[0].ConnectionString.Split(';');
                                string dbConnection = splitout[0] + ";" + splitout[1] + "; Integrated Security=SSPI;";

                                TfsTeamService teamService = new TfsTeamService();
                                teamService.Initialize(tpc);
                                if (aOptions.getArg("teams") != null)
                                {
                                    foreach (KeyValuePair<string, string> team in options.TeamSeparated(aOptions.getArg("teams")))
                                    {
                                        foreach (Project project in projectList)
                                        {
                                            if (project.name == team.Key)
                                                options.addTeam(project.teams[team.Value]);
                                        }
                                    }
                                }
                        }
                    }

                }
            }
            catch (Exception e)
            {
                Console.WriteLine("The TFS Collection URL is invalid: 404");
                Environment.Exit(1);
            }
        }

        static void optionMenu()
        {
            List<KeyValuePair<String, String>> teamChoices = new List<KeyValuePair<String, String>>();
            Int32 selectedIndex = -1;
            
            try
            {
                Console.WriteLine("Please select one or more teams to rollover. \nUse All to rollover all teams in the collection");
                Console.WriteLine("Ex: 1 <enter> will rollover team 1.  \n    1,2,3 <enter> will rollover teams 1, 2 and 3\n\n");
                
                foreach (Project project in projectList)
                {
                    Console.WriteLine("Project > " + project.name);
                    foreach (var team in project.teams)
                    {
                        teamChoices.Add(new KeyValuePair<string, string>(team.Key, team.Value));
                        Console.WriteLine("\t" + teamChoices.Count + ": " + team.Key);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Couldn't connect to the specified team project collection\n" + options.CollectionUri + "\n" + e);
                return;
            }

            while(true)
            {
                Console.Write("\n:>");
                string selection = Console.ReadLine();
                if (selection == "All")
                {
                    foreach (KeyValuePair<string,string> choice in teamChoices)
                    {
                        options.addTeam(choice.Value);
                    }

                    Console.WriteLine("Rolling over all teams");
                    break;
                }
                else
                {
                    string[] selections = selection.Split(',');
                    string actualSelection=null;
                    foreach (string sel in selections)
                    {
                        if (Int32.TryParse(sel, out selectedIndex))
                        {
                            if (selectedIndex > 0 && selectedIndex <= teamChoices.Count())
                            {
                                options.addTeam(teamChoices[selectedIndex - 1].Value);
                                if(actualSelection!=null)
                                    actualSelection+=", ";
                                actualSelection += selectedIndex;
                            }
                        }
                    }
                    if (options.hasTfsTeams())
                    {
                        Console.WriteLine("Rolling over teams "+actualSelection);
                        break;
                    }
                }
                Console.WriteLine("Sorry, I couldn't process your selection, please try again");
            }
            
        
        }

        static void optionReader(String path)
        {
            oSer = new SharpSerializer();
            try
            {
                options = (AgileRollover.Options)oSer.Deserialize(path);
            }
            catch (Exception e)
            {
                Console.WriteLine("There was an error reading the options file");
                Console.WriteLine(e.Message);
            }
        }

        static void optionWriter(String path)
        {
            oSer = new SharpSerializer();
            try
            {
                oSer.Serialize(options,path);
            }
            catch (Exception e)
            {
                Console.WriteLine("There was an error writing to file");
                Console.WriteLine(e.Message);
            }
        }
    }
}
